package marseillaisdu90.student_life;

import marseillaisdu90.modele.Modele;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Handler;
import android.util.*;
import android.view.*;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Toast;

public class FenetreJeuView extends SurfaceView implements SurfaceHolder.Callback {
	
	private StudentLifeThread mThread;
	private float oldDist;
	private PointF mid;
	private PointF start;
	private float zoomDepart;
	private Matrix matrix;
	private Matrix savedMatrix;
	public static final int NONE = 0;
	public static final int DRAG = 1;
	public static final int ZOOM = 2;
	public static int mode = NONE;
	public Modele modele;
	float[] m_matrixValues = new float[9];
	private long lastTouchTime = -1;
	
	public FenetreJeuView(Context context) {
		super(context);
		initialisation(context);
	}
	
	public FenetreJeuView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initialisation(context);
    }
	
	public void initialisation(Context context) {
		SurfaceHolder holder = getHolder();
		holder.addCallback(this);
		mThread = new StudentLifeThread(holder, context, new Handler());
		setFocusable(true); // need to get the key events
		oldDist = 0.0f;
		mode = 0;
        mid=new PointF(0,0);
        start=new PointF(0,0);
        zoomDepart = 1.0f;
    	matrix = MonApplication.matrix;
    	savedMatrix = new Matrix();
    	modele = MonApplication.modele;
    	isInEditMode();
	}
	

	public StudentLifeThread getThread() {
		return mThread;
	}

	public void surfaceCreated(SurfaceHolder holder) {
		Log.i("redemarre thread","redemarre thread");
		if(!mThread.isAlive()) {
			mThread.setRunning(true);
			mThread.start();
		}
	}

	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		Log.i("surfaceChanged","surfaceChanged");
	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		
		Log.i("attend suppr thread","attend suppr thread");
		/*
		boolean retry = true;
		mThread.setRunning(false);
		while (retry) {
			try {
				mThread.join();
				retry = false;
			} catch (InterruptedException e) {
			}
		}
		*/
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		mThread.doKeyDown(keyCode, event);
		return super.onKeyDown(keyCode, event);
	}

	@Override
	public boolean onKeyUp(int keyCode, KeyEvent event) {
		mThread.doKeyUp(keyCode, event);
		return super.onKeyUp(keyCode, event);
	}

	public StudentLifeThread getmThread() {
		return mThread;
	}

	
	@Override
	public /*synchronized*/ boolean onTouchEvent(MotionEvent event) {
				
		switch (event.getAction() & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			savedMatrix.set(matrix);
			start.set(event.getX(), event.getY());
			Log.i("test", "mode=DRAG");
			mode = DRAG;
			
			//double clic
			long thisTime = System.currentTimeMillis();
			if (thisTime - lastTouchTime < 250) {
				matrix.set(savedMatrix);
				matrix.reset();
				lastTouchTime = -1;
			}
			else
				lastTouchTime = thisTime;
			
			break;
		case MotionEvent.ACTION_POINTER_DOWN:
			oldDist = spacing(event);
			Log.i("test", "oldDist=" + oldDist);
			if (oldDist > 10f) {
				savedMatrix.set(matrix);
				midPoint(mid, event);
				mode = ZOOM;
				Log.i("test", "mode=ZOOM");
			}
			break;
		case MotionEvent.ACTION_MOVE:
			if (mode == DRAG) {
				matrix.set(savedMatrix);
				float x = event.getX() - start.x;
				float y = event.getY() - start.y;

				matrix.getValues(m_matrixValues);
                //float currentY = m_matrixValues[Matrix.MTRANS_Y];
                //float currentX = m_matrixValues[Matrix.MTRANS_X];  
				
				int longueur = (int) (mThread.background.getWidth() * m_matrixValues[Matrix.MSCALE_X]);
				int hauteur = (int) (mThread.background.getHeight() * m_matrixValues[Matrix.MSCALE_X]);
				
                //Log.i("tag", "curentX : "+(m_matrixValues[Matrix.MTRANS_X]+x)+", curentY : "+(m_matrixValues[Matrix.MTRANS_Y]+y) + ", x : " + x + ", y : " + y + ", width : " + (longueur - this.getWidth())+", height : " + Math.abs(hauteur - this.getHeight()));
				
                if(m_matrixValues[Matrix.MTRANS_X] + x > 0 && x > 0)
                	x = - m_matrixValues[Matrix.MTRANS_X];
                else if((-(m_matrixValues[Matrix.MTRANS_X] + x)) > Math.abs(longueur - this.getWidth()) && x < 0)
                	x = - Math.abs(longueur - this.getWidth()) - m_matrixValues[Matrix.MTRANS_X];
                
                
                if(m_matrixValues[Matrix.MTRANS_Y] + y > 0 && y > 0)
                	y = - m_matrixValues[Matrix.MTRANS_Y];
                else if((-(m_matrixValues[Matrix.MTRANS_Y] + y)) > Math.abs(hauteur - this.getHeight()) && y < 0)
                	y = - Math.abs(hauteur - this.getHeight()) - m_matrixValues[Matrix.MTRANS_Y];
				
                if(longueur - this.getWidth() <=0 && x < 0)
                	x = 0;
                if(hauteur - this.getHeight() <=0 && y < 0)
                	y = 0;
                

                
                //Log.i("translate","x : "+x+", y : "+y);
                
				matrix.postTranslate(x, y);
			} else if (mode == ZOOM) {
				float newDist = spacing(event);
				Log.i("test", "newDist=" + newDist);
				if (newDist > 10f) {
					matrix.set(savedMatrix);
					float scale = newDist / oldDist;
					//if(scale < 1.0)
					//	scale = 1.0f;
					matrix.postScale(scale, scale, mid.x, mid.y);
					Log.i("test","scale : "+scale);
				}
			}
			break;
		case MotionEvent.ACTION_UP:
			mode = NONE;
		case MotionEvent.ACTION_POINTER_UP:
			mode = NONE;
			Log.i("test", "mode=NONE");
			break;
		}
		
		// Perform the transformation
		mThread.setMatrix(matrix);
		
		mThread.MAJIG();
		
		
		return true;
	}
	
	public boolean onTrackballEvent(MotionEvent event) {
		
		Log.i("dpad","track");
		
		int me = event.getAction() & MotionEvent.ACTION_MASK;
		
		if(event.getAction() == MotionEvent.ACTION_UP) {
			action();
		}
		else if(me == MotionEvent.ACTION_MOVE) {
			Log.i("dpad","move");
            
            deplacement(event.getX() * event.getXPrecision(), event.getY() * event.getYPrecision());
		}
		
		return true;
	}
	
	public synchronized void action() {
		if((modele.inv.estRempli()==false)&&(modele.inv.nbObjet()!=12))
			mThread.objetRamasse();
		mThread.InteractionPNJ();
		mThread.MAJIG();
	}
	
	public synchronized void deplacement(float x, float y) {
		Log.i("dpad","move");
		
        if(x < 0 && modele.ListePiece.id.get(modele.nopiece_courante).topographie[modele.joueur.getPosY()][modele.joueur.getPosX()-1]==0 && modele.fini==true) {
			Log.i("test", "Gauche");
        	modele.fini = false;
        	modele.joueur.allerGauche();
			modele.joueur.setDirection("Gauche");
			modele.depl_posX = 32;
        	mThread.position = mThread.GAUCHE;
        	mThread.nombreDeplacementRestant ++/*= -x*/;
        }
        else if(x > 0 && modele.ListePiece.id.get(modele.nopiece_courante).topographie[modele.joueur.getPosY()][modele.joueur.getPosX()+1]==0 && modele.fini==true) {
        	//Log.i("test","" + modele.joueur.getPosY() + ", "+ modele.joueur.getPosX());
        	//Log.i("test", "Droite");
        	modele.fini = false;
        	modele.joueur.allerDroite();
			modele.joueur.setDirection("Droite");
			modele.depl_posX = 32;
        	mThread.position = mThread.DROITE;
        	mThread.nombreDeplacementRestant ++/*= x*/;
        }
        else if(y < 0 && modele.ListePiece.id.get(modele.nopiece_courante).topographie[modele.joueur.getPosY()-1][modele.joueur.getPosX()]==0 && modele.fini==true) {
        	Log.i("test", "Haut");
        	modele.fini = false;
        	modele.joueur.allerHaut();
			modele.joueur.setDirection("Haut");
			modele.depl_posY = 32;
        	mThread.position = mThread.HAUT;
        	mThread.nombreDeplacementRestant ++/*= -y*/;
        }
        else if(y > 0 && modele.ListePiece.id.get(modele.nopiece_courante).topographie[modele.joueur.getPosY()+1][modele.joueur.getPosX()]==0 && modele.fini==true) {
        	Log.i("test", "Bas");
        	modele.fini = false;
        	modele.joueur.allerBas();
			modele.joueur.setDirection("Bas");
			modele.depl_posY = 32;
        	mThread.position = mThread.BAS;
        	mThread.nombreDeplacementRestant ++/*= y*/;
        }
        else if(x < 0) {
        	mThread.anciennePos = mThread.GAUCHE;
        	modele.joueur.setDirection("Gauche");
        }
        else if(x > 0) {
        	mThread.anciennePos = mThread.DROITE;
        	modele.joueur.setDirection("Droite");
        }
        else if(y < 0) {
        	mThread.anciennePos = mThread.HAUT;
        	modele.joueur.setDirection("Haut");
        }
        else if(y > 0) {
        	mThread.anciennePos = mThread.BAS;
        	modele.joueur.setDirection("Bas");
        }
        
        Log.i("dpad","x : " + x + ", y : " + y);
        mThread.MAJIG();
	}
	
	public boolean onKeyDown(MotionEvent event) {
		
		Log.i("dpad","key");
		
		int me = event.getAction() & MotionEvent.ACTION_MASK;
		
		if(me == MotionEvent.ACTION_DOWN)
			Log.i("dpad","r");
		else if(me == KeyEvent.KEYCODE_DPAD_DOWN)
			Log.i("dpad","d");
		else if(me == KeyEvent.KEYCODE_DPAD_CENTER)
			Log.i("dpad","c");
		return true;
	}
	
	public float spacing(MotionEvent event) {
		float x = event.getX(0) - event.getX(1);
		float y = event.getY(0) - event.getY(1);
		return FloatMath.sqrt(x * x + y * y);
	}
	
	public void midPoint(PointF point, MotionEvent event) {
		float x = event.getX(0) + event.getX(1);
		float y = event.getY(0) + event.getY(1);
		point.set(x / 2, y / 2);
	}
	
}
